#ifndef _ML_H_
#define _ML_H_

#ifdef __gl_h_
	typedef GLenum		MLenum;
	typedef GLboolean	MLboolean;
	typedef GLbitfield	MLbitfield;
	typedef GLvoid		MLvoid;
	typedef GLbyte		MLbyte;         /* 1-byte signed */
	typedef GLshort		MLshort;        /* 2-byte signed */
	typedef GLint		MLint;          /* 4-byte signed */
	typedef GLubyte		MLubyte;        /* 1-byte unsigned */
	typedef GLushort	MLushort;       /* 2-byte unsigned */
	typedef GLuint		MLuint;         /* 4-byte unsigned */
	typedef GLsizei		MLsizei;        /* 4-byte signed */
	typedef GLfloat		MLfloat;        /* single precision float */
	typedef GLclampf	MLclampf;       /* single precision float in [0,1] */
	typedef GLdouble	MLdouble;       /* double precision float */
	typedef GLclampd	MLclampd;       /* double precision float in [0,1] */
#else
	typedef unsigned int    MLenum;
	typedef unsigned char   MLboolean;
	typedef unsigned int    MLbitfield;
	typedef void            MLvoid;
	typedef signed char     MLbyte;         /* 1-byte signed */
	typedef short           MLshort;        /* 2-byte signed */
	typedef int             MLint;          /* 4-byte signed */
	typedef unsigned char   MLubyte;        /* 1-byte unsigned */
	typedef unsigned short  MLushort;       /* 2-byte unsigned */
	typedef unsigned int    MLuint;         /* 4-byte unsigned */
	typedef int             MLsizei;        /* 4-byte signed */
	typedef float           MLfloat;        /* single precision float */
	typedef float           MLclampf;       /* single precision float in [0,1] */
	typedef double          MLdouble;       /* double precision float */
	typedef double          MLclampd;       /* double precision float in [0,1] */
#endif

typedef union {
	struct{
		MLfloat x;
		MLfloat y;
	};
	MLfloat a[2];
}MLvec2;

typedef union {
	struct{
		MLfloat x;
		MLfloat y;
		MLfloat z;
	};
	MLfloat a[3];
}MLvec3;

typedef union {
	struct{
		MLfloat x;
		MLfloat y;
		MLfloat z;
		MLfloat w;
	};
	MLfloat a[4];
}MLvec4;

typedef union{
	MLvec2 v[2];
	MLfloat a[4];
	MLfloat m[2][2];
}MLmat2;

typedef union{
	MLvec3 v[3];
	MLfloat a[9];
	MLfloat m[3][3];
}MLmat3;

typedef union{
	MLvec4 v[4];
	MLfloat a[16];
	MLfloat m[4][4];
}MLmat4;

/* vector & matrix initial */
void mlZero2v(MLvec2*);
void mlZero2m(MLmat2*);
void mlZero3v(MLvec3*);
void mlZero3m(MLmat3*);
void mlZero4v(MLvec4*);
void mlZero4m(MLmat4*);

void mlVec2f(MLvec2*, MLfloat*);
void mlVec2(MLvec2*, MLvec2*);
void mlVec3f(MLvec3*, MLfloat*);
void mlVec3(MLvec3*, MLvec3*);
void mlVec4f(MLvec4*, MLfloat*);
void mlVec4(MLvec4*, MLvec4*);

void mlIdentity2(MLmat2*);
void mlMat2f(MLmat2*, MLfloat*);
void mlMat2(MLmat2*, MLmat2*);
void mlIdentity3(MLmat3*);
void mlMat3f(MLmat3*, MLfloat*);
void mlMat3(MLmat3*, MLmat3*);
void mlIdentity4(MLmat4*);
void mlMat4f(MLmat4*, MLfloat*);
void mlMat4(MLmat4*, MLmat4*);

void mlVecNeg2(MLvec2*);
void mlVecNeg2v(MLvec2*, MLvec2*);
void mlVecNeg3(MLvec3*);
void mlVecNeg3v(MLvec3*, MLvec3*);
void mlVecNeg4(MLvec4*);
void mlVecNeg4v(MLvec4*, MLvec4*);
void mlMatNeg2(MLmat2*);
void mlMatNeg2m(MLmat2*, MLmat2*);
void mlMatNeg3(MLmat3*);
void mlMatNeg3m(MLmat3*, MLmat3*);
void mlMatNeg4(MLmat4*);
void mlMatNeg4m(MLmat4*, MLmat4*);

void mlVecAdd2(MLvec2*, MLfloat);
void mlVecAdd2f(MLvec2*, MLvec2*, MLfloat);
void mlVecAdd2v(MLvec2*, MLvec2*, MLvec2*);
void mlMatAdd2(MLmat2*, MLfloat);
void mlMatAdd2f(MLmat2*, MLmat2*, MLfloat);
void mlMatAdd2m(MLmat2*, MLmat2*, MLmat2*);
void mlVecAdd3(MLvec3*, MLfloat);
void mlVecAdd3f(MLvec3*, MLvec3*, MLfloat);
void mlVecAdd3v(MLvec3*, MLvec3*, MLvec3*);
void mlMatAdd3(MLmat3*, MLfloat);
void mlMatAdd3f(MLmat3*, MLmat3*, MLfloat);
void mlMatAdd3m(MLmat3*, MLmat3*, MLmat3*);
void mlVecAdd4(MLvec4*, MLfloat);
void mlVecAdd4f(MLvec4*, MLvec4*, MLfloat);
void mlVecAdd4v(MLvec4*, MLvec4*, MLvec4*);
void mlMatAdd4(MLmat4*, MLfloat);
void mlMatAdd4f(MLmat4*, MLmat4*, MLfloat);
void mlMatAdd4m(MLmat4*, MLmat4*, MLmat4*);

void mlVecSub2(MLvec2*, MLfloat);
void mlVecSub2f(MLvec2*, MLvec2*, MLfloat);
void mlVecSub2v(MLvec2*, MLvec2*, MLvec2*);
void mlMatSub2(MLmat2*, MLfloat);
void mlMatSub2f(MLmat2*, MLmat2*, MLfloat);
void mlMatSub2m(MLmat2*, MLmat2*, MLmat2*);
void mlVecSub3(MLvec3*, MLfloat);
void mlVecSub3f(MLvec3*, MLvec3*, MLfloat);
void mlVecSub3v(MLvec3*, MLvec3*, MLvec3*);
void mlMatSub3(MLmat3*, MLfloat);
void mlMatSub3f(MLmat3*, MLmat3*, MLfloat);
void mlMatSub3m(MLmat3*, MLmat3*, MLmat3*);
void mlVecSub4(MLvec4*, MLfloat);
void mlVecSub4f(MLvec4*, MLvec4*, MLfloat);
void mlVecSub4v(MLvec4*, MLvec4*, MLvec4*);
void mlMatSub4(MLmat4*, MLfloat);
void mlMatSub4f(MLmat4*, MLmat4*, MLfloat);
void mlMatSub4m(MLmat4*, MLmat4*, MLmat4*);

void mlMul2vf(MLvec2*, MLvec2*, MLfloat);
void mlMul2vm(MLvec2*, MLvec2*, MLmat2*);
void mlMul2mv(MLvec2*, MLmat2*, MLvec2*);
void mlMul2mf(MLmat2*, MLmat2*, MLfloat);
void mlMul2mm(MLmat2*, MLmat2*, MLmat2*);
void mlMul3vf(MLvec3*, MLvec3*, MLfloat);
void mlMul3vm(MLvec3*, MLvec3*, MLmat3*);
void mlMul3mv(MLvec3*, MLmat3*, MLvec3*);
void mlMul3mf(MLmat3*, MLmat3*, MLfloat);
void mlMul3mm(MLmat3*, MLmat3*, MLmat3*);
void mlMul4vf(MLvec4*, MLvec4*, MLfloat);
void mlMul4vm(MLvec4*, MLvec4*, MLmat4*);
void mlMul4mv(MLvec4*, MLmat4*, MLvec4*);
void mlMul4mf(MLmat4*, MLmat4*, MLfloat);
void mlMul4mm(MLmat4*, MLmat4*, MLmat4*);

MLfloat mlLength2(MLvec2*);
MLfloat mlLength3(MLvec3*);
MLfloat mlLength4(MLvec4*);

MLfloat mlDot2(MLvec2*, MLvec2*);
MLfloat mlDot3(MLvec3*, MLvec3*);
MLfloat mlDot4(MLvec4*, MLvec4*);

void mlReflect2(MLvec2*, MLvec2*);
void mlReflect2v(MLvec2*, MLvec2*, MLvec2*);
void mlReflect3(MLvec3*, MLvec3*);
void mlReflect3v(MLvec3*, MLvec3*, MLvec3*);
void mlReflect4(MLvec4*, MLvec4*);
void mlReflect4v(MLvec4*, MLvec4*, MLvec4*);

void mlCross(MLvec3*, MLvec3*, MLvec3*);

void mlNormalize2v(MLvec2*, MLvec2*);
void mlNormalize2(MLvec2*);
void mlNormalize3v(MLvec3*, MLvec3*);
void mlNormalize3(MLvec3*);
void mlNormalize4v(MLvec4*, MLvec4*);
void mlNormalize4(MLvec4*);

void mlCompMul2(MLmat2*, MLmat2*, MLmat2*);
void mlCompMul3(MLmat3*, MLmat3*, MLmat3*);
void mlCompMul4(MLmat4*, MLmat4*, MLmat4*);

void mlTranspose2m(MLmat2 *, MLmat2 *);
void mlTranspose2(MLmat2 *);
void mlTranspose3m(MLmat3 *, MLmat3 *);
void mlTranspose3(MLmat3 *);
void mlTranspose4m(MLmat4 *, MLmat4 *);
void mlTranspose4(MLmat4 *);

typedef enum{
	ML_PERSPECTIVE = 0,
	ML_OTHOGONAL,
}mlProjModes;

void mlViewMat(MLmat4 *, MLvec3*, MLvec3*, MLvec3 *);
void mlRotateXMat(MLmat4*, MLfloat);
void mlRotateYMat(MLmat4*, MLfloat);
void mlRotateZMat(MLmat4*, MLfloat);
void mlRotateAnyMat(MLmat4*, MLvec3*, MLfloat);
void mlTranslateMat(MLmat4*, MLvec3*);
void mlProjMat(MLmat4*, MLvec3*, MLvec3*, mlProjModes);

#endif /* _ML_H_ */
